package com.yusp75.myexam.data


import android.content.Context
import android.net.Uri
import android.util.Log
import androidx.lifecycle.lifecycleScope
import com.yusp75.myexam.com.yusp75.myexam.util.ProgressState
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.launch
import org.apache.poi.ss.usermodel.*
import org.apache.poi.xssf.usermodel.XSSFWorkbook
import java.io.InputStream
import kotlin.compareTo
import kotlin.text.isEmpty
import kotlin.text.toFloatOrNull

class ExcelToRoomHelper(
    private val bookDao: BookDao,
    private val questionDao: QuestionDao
) {
    var bookId: Int = 0

    // 从assets读取Excel文件
    fun getWorkbook(context: Context, fileName: String): Workbook? {
        return try {
            val inputStream: InputStream = context.assets.open(fileName)
            XSSFWorkbook(inputStream)

        } catch (e: Exception) {
            e.printStackTrace()
            null
        }
    }

    // 从uri读取Excel文件
    fun getWorkbook(context: Context, uri: Uri?): Workbook? {
        if (uri == null) return null

        return try {
            context.contentResolver.openInputStream(uri)?.use { stream ->
                XSSFWorkbook(stream)
            }
        } catch (e: Exception) {
            e.printStackTrace()
            null
        }
    }

    // 书信息
    suspend fun getBook(workbook: Workbook?, sheetName: String) {

        workbook?.getSheet(sheetName)?.let { sheet ->
            try {
                val bookName = sheet.getRow(0)?.getCell(1)?.toString()?.trim().orEmpty()
                if (bookName.isBlank()) return@let

                bookId = bookDao.getIdByName(bookName) ?: bookDao.insertBook(
                    Book(
                        name = bookName,
                        author = sheet.getRow(1)?.getCell(1)?.toString()?.trim().orEmpty(),
                        releaseTime = sheet.getRow(2)?.getCell(1)?.toString()?.trim().orEmpty(),
                        version = sheet.getRow(3)?.getCell(1)?.toString()?.trim().orEmpty(),
                        comment = "",
                        isSelected = false
                    )
                ).toInt()

                // 处理评论（单独处理因为可能为null）
                sheet.getRow(4)?.getCell(1)?.toString()?.trim()?.let { comment ->
                    bookDao.updateBookComment(bookId, comment)
                }
            } catch (e: Exception) {
                Log.e("ExcelProcessor", "处理表格数据出错", e)
            }
        }

    }

    // 读取Excel数据（第一行为表头）
    fun getExcelData(workbook: Workbook?, sheetName: String): List<Map<String, String>> {
        val dataList = mutableListOf<Map<String, String>>()
        workbook?.let {
            val sheet = it.getSheet(sheetName) // 获取工作表
            // 数据类型
            // 根据答案判断

            // 题目开始
            val headerRow = sheet.getRow(0) // 获取表头行
            // 遍历数据行（从第2开始）
            for (i in 1 until sheet.physicalNumberOfRows) {
                val dataRow = sheet.getRow(i)
                val rowData = mutableMapOf<String, String>()

                // 遍历单元格
                for (j in 0 until headerRow.physicalNumberOfCells) {
                    val header = headerRow.getCell(j).toString()
                    val value = dataRow?.getCell(j)?.toString() ?: ""
                    rowData[header] = value
                    rowData["类型"] = sheetName
                }
                dataList.add(rowData)
            }
        }
        return dataList
    }

    // 处理记录
    fun processRecords(book: Int, data: List<Map<String, String>>): Flow<ProgressState> = flow {
        emit(ProgressState.Pending)
        var i = 0
        data.let {
            it.forEach { item ->
                val idx = item["序号"]?.toFloatOrNull()?.toInt() ?: -1
                val a = item["题目"] ?: ""
                val b = item["答案"] ?: ""
                val c = item["解析"] ?: ""
                val d = item["多选"]?.equals("是") == true
                //val d = item["多选"]?.apply { this == "是"}
                // 类型

                if ((idx != -1) and (!a.isEmpty()) and (!b.isEmpty())) {
                    questionDao.insertQuestion(
                        Question(
                            questionIdx = idx,
                            bookId = bookId,
                            questionType = item["类型"] ?: "选择",
                            content = a,
                            answer = b,
                            analysis = c,
                            favorite = false,
                            multipleChoice = d
                        ) // Question
                    )
                    i++
                }

                // 更新进度
                val progress = ((i + 1) * 100) / data.size
                emit(ProgressState.Processing(progress))
            }
        }
        emit(ProgressState.Completed) // 完成
        println("导入记录：$i")
    }.catch { e ->
        emit(ProgressState.Error(e.message ?: "Unknown error"))
    }.flowOn(Dispatchers.IO)

    // 写到数据库
    fun writeToRoom(
        context: Context,
        fileName: String? = null,
        uri: Uri? = null
    ): Flow<ProgressState> = flow {
        // 参数校验逻辑
        when {
            fileName != null && uri != null -> {
                emit(ProgressState.Error("冲突: 不能同时指定fileName和uri"))
                return@flow
            }

            fileName == null && uri == null -> {
                emit(ProgressState.Error("错误: 必须提供fileName或uri"))
                return@flow
            }

            fileName?.takeIf { it.isNotBlank() }?.endsWith(".xlsx") == false -> {
                emit(ProgressState.Error("文件格式错误: 仅支持.xlsx"))
                return@flow
            }
        }

        // 获取Workbook（含异常处理）
        val book = try {
            when {
                !fileName.isNullOrBlank() -> getWorkbook(context, fileName)
                uri != null -> getWorkbook(context, uri)
                else -> null
            } ?: run {
                emit(ProgressState.Error("无法解析Excel文件"))
                return@flow
            }
        } catch (e: Exception) {
            emit(ProgressState.Error("读取失败: ${e.message}"))
            return@flow
        }

        // 书的信息
        getBook(book, "说明")

        // 处理Sheet数据
        try {
            val data0 = getExcelData(book, "判断")
            val data1 = getExcelData(book, "选择")
            val mergedData = data0 + data1  // 合并列表保持顺序
            // 更新书的问题数

            processRecords(bookId, mergedData).collect { emit(it) }  // 转发子Flow状态
        } catch (e: Exception) {
            emit(ProgressState.Error("数据处理失败: ${e.message}"))
        }
    }.flowOn(Dispatchers.IO)  // 指定IO线程

    fun String.getFileName(): String {
        val lastDotIndex = lastIndexOf('.')
        return if (lastDotIndex > 0) substring(0, lastDotIndex) else this
    }

    suspend fun isFirst(): Boolean {
        return questionDao.getQuestionCountFlow().first().total == 0
    }

    // demo
    fun readContentUri(context: Context, uri: Uri): String? {
        return try {
            context.contentResolver.openInputStream(uri)?.use { stream ->
                stream.bufferedReader().use { it.readText() }
            }
        } catch (e: Exception) {
            e.printStackTrace()
            null
        }
    }


//
}


